package team.lhc.cms.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import team.lhc.cms.dto.LegalParking;
import team.lhc.cms.entity.License;
import team.lhc.cms.entity.ParkingRecord;
import team.lhc.cms.entity.ParkingSpace;
import team.lhc.cms.mapper.LicenseMapper;
import team.lhc.cms.mapper.ParkingRecordMapper;
import team.lhc.cms.mapper.ParkingSpaceMapper;
import team.lhc.cms.service.ParkingService;
import team.lhc.cms.util.ExcelUtil;
import team.lhc.cms.util.JsonResult;
import team.lhc.cms.util.RedisUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 文
 * @description 停车/车位服务层接口类
 */
@Service
public class ParkingServiceImpl implements ParkingService {

    @Autowired
    ParkingRecordMapper parkingRecordMapper;

    @Autowired
    ParkingSpaceMapper parkingSpaceMapper;

    @Autowired
    LicenseMapper licenseMapper;

    @Autowired
    RedisUtil redisUtil;

    //免费时间
    @Value("${parking.freeTime}")
    private double freeTime;

    //停车单价
    @Value("${parking.unitPrice}")
    private double unitPrice;

    //封顶价格
    @Value("${parking.cappedPrice}")
    private double cappedPrice;

    /**
     * 设置车牌号
     * @author 文
     * @param map
     * @param token
     * @return
     */
    @Override
    public String setLicense(Map<String,Object> map, String token) {
        Map<String,Object> data = (Map<String, Object>) redisUtil.hget(token);
        Integer uid = (Integer) data.get("uid");
        List<String> list = (List<String>) map.get("licenses");
        //获取当前数据库数据
        List<License> licenses = licenseMapper.getListByUid(uid);
        if (licenses == null){
            return JsonResult.failed("没有添加车牌的权限,如有需要,请与物管联系");
        }

        //更新
        for (int i = 0; i < licenses.size(); i++) {
            licenseMapper.setLicenseByLid(licenses.get(i).getLid(),list.get(i));
        }
        return JsonResult.success();
    }

    /**
     * 设置(更新)某个车位的信息
     * @author 文
     * @param parkingSpace
     * @return
     */
    @Override
    public String setParkingSpaceInfo(ParkingSpace parkingSpace) {
        Integer update = parkingSpaceMapper.updateByPid(parkingSpace);
        //当操作是绑定车位给用户时,给用户新增两个设置车牌的权限
        if (parkingSpace.getUid() > 0){
            for (int i = 0; i < 2; i++) {
                licenseMapper.iniLincense(parkingSpace.getUid());
            }
        }
        return update == 0 ? JsonResult.failed() : JsonResult.success();
    }

    /**
     * 入场检查
     * @author 文
     * @param license
     * @return
     */
    @Override
    public String entry(String license) {
        //判空操作
        Assert.notNull(license,"车牌号为空,请重新扫描");

        //判断是否是临时停车牌
        Boolean exist = redisUtil.hasKey("tempLicense", license);
        if (Boolean.TRUE.equals(exist)){
            //临时停车,系统分配车位
            //此处为按需分配,第二版可升级为按区域分配
            String parkingSpace = null;
            parkingSpace = parkingSpaceMapper.findOneFreeOnTemp().getPid();
            if (parkingSpace == null){
                //没有临时车位,从租售车位但无人租售的车位中分配
                parkingSpace = parkingSpaceMapper.findOneFreeOnOther().getPid();
                if (parkingSpace == null){
                    //无可用车位,拒绝入场
                    return JsonResult.failed(104,"无可用车位,拒绝入场");
                }
            }
            parkingSpaceMapper.updateStatusByPid(1,parkingSpace);
            parkingRecordMapper.save(new ParkingRecord(license,parkingSpace,now()));
            return JsonResult.success(103,license + " 欢迎入场,请停到 " + parkingSpace + " 号车位上");
        }

        //判断是否存在车牌记录
        List<LegalParking> legalParkings = parkingSpaceMapper.findLegalParking(license);
        if (legalParkings == null || legalParkings.isEmpty()){
            return JsonResult.failed(104,"车牌无记录或您名下无空闲车位");
        }
        parkingRecordMapper.save(new ParkingRecord(license,legalParkings.get(0).getPid(),now()));
        parkingSpaceMapper.updateStatusByPid(1,legalParkings.get(0).getPid());
        return JsonResult.success(103,license + ", 欢迎回家");
    }

    /**
     * 出场计费
     * @author 文
     * @param license
     * @return
     */
    @Override
    public String departure(String license) throws ParseException {
        //判空操作
        Assert.notNull(license,"车牌号为空,请重新扫描");
        //获取当前时间
        String now = now();
        //寻找停车记录
        ParkingRecord parkingRecord = parkingRecordMapper.findRecentRecordByLicense(license);
        //还原车位状态
        parkingSpaceMapper.updateStatusByPid(0,parkingRecord.getPid());
        //查找长期车牌库中是否有该车牌
        License lic = licenseMapper.findByLicense(license);
        if (lic == null){
            //此车为临时车
            //计算停车费用
            Map<String,Object> fee = billing(parkingRecord.getEntryTime(),now);
            //记录出场时间和费用
            parkingRecordMapper.updateDepartureTimeAndFee(parkingRecord.getRid(),now, (String) fee.get("fee"));
            return JsonResult.success(101,license + " (临时车), 停车时长 " + fee.get("time") + " 小时,收费 " + fee.get("fee") + " 元",fee);
        }
        //记录出场时间和费用
        parkingRecordMapper.updateDepartureTimeAndFee(parkingRecord.getRid(),now,"0");
        return JsonResult.success(101,license + ", 一路平安!");
    }

    /**
     * 预导入
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public String importParkingSpace(MultipartFile file) throws IOException {
        //解析导入的excel的内容
        List<List<String>> lists = ExcelUtil.importExcel(file);
        List<ParkingSpace> parkingSpaces = new ArrayList<>();
        ParkingSpace parkingSpace = null;
        //封装内容为ParkingSpace类型
        for (int i = 0; i < lists.size(); i++) {
            parkingSpace = new ParkingSpace();
            parkingSpace.setPid(lists.get(i).get(0));
            parkingSpace.setType(Integer.valueOf(lists.get(i).get(1)));
            parkingSpace.setStatus(Integer.valueOf(lists.get(i).get(2)));
            parkingSpaces.add(parkingSpace);
        }
        Integer save = parkingSpaceMapper.batchSave(parkingSpaces);
        return JsonResult.success("成功导入" + save + "个车位信息");
    }

    /**
     * 下载车位导入模板
     * @author 文
     * @param response
     * @throws IOException
     */
    @Override
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        List<List<String>> lists = new ArrayList<>();
        List<String> list = new ArrayList<>();
        list.add("车位名(建议不要用中文)");
        list.add("车位类型：0临时车位，1可出售车位，2可出租车位");
        list.add("车位状态：0未停，1已停");
        lists.add(list);
        ExcelUtil.exportExcel(response,lists,"车位1","车位导入表格",25);
    }

    /**
     * 获取用户可设置车位数和已存在车牌
     * @author 文
     * @param token
     * @return
     */
    @Override
    public String getLicense(String token) {
        Map<String,Object> data = (Map<String, Object>) redisUtil.hget(token);
        Integer uid = (Integer) data.get("uid");

        List<License> licenses = licenseMapper.getListByUid(uid);
        if (licenses == null){
            return JsonResult.failed("没有添加车牌的权限,如有需要,请与物管联系");
        }

        //封装信息
        data = new HashMap<>();
        data.put("num",licenses.size());
        data.put("licenses",licenses);

        return JsonResult.success(data);
    }

    /**
     * 获取停车位信息列表
     * @author 文
     * @return
     */
    @Override
    public String getParkingSpaceList() {
        Map<String,Object> map = new HashMap<>();
        map.put("parkingSpaces",parkingSpaceMapper.getParkingSpaceList());
        return JsonResult.success(map);
    }


    /**
     * 计算费用(前 freeTime 个小时免费，超出时按 unitPrice 元/时收费，每24小时内封顶 cappedPrice 元（不足一小时按一小时计算）)
     * @author 文
     * @param entryTime
     * @param now
     * @return
     */
    private Map<String, Object> billing(String entryTime, String now) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map<String,Object> map = new HashMap<>();
        double fee = 0;
        //实际时间间隔(时)
        double diff = (double) (simpleDateFormat.parse(now).getTime() - simpleDateFormat.parse(entryTime).getTime()) / (1000 * 60 * 60);
        map.put("time",String.format("%.2f",diff));
        //计费时间间隔(时)
        double calDiff = Math.ceil(diff);
        if (calDiff <= freeTime){
            //若停车时长在免费时长内则免费
            map.put("fee",String.valueOf(fee));
            return map;
        }

        //封顶时长(若大于等于24即不封顶)
        double cappedTime = cappedPrice / unitPrice;

        if (cappedTime <= 24){
            //封顶的情况下
            if (calDiff <= cappedTime ){
                //若停放时长小于封顶时长
                fee = calDiff * unitPrice;
                map.put("fee",String.valueOf(fee));
                return map;
            }else {
                //停放时长大于封顶时长
                //封顶天数
                double cappedDay = calDiff / 24;
                //封顶次数
                double cappedFrequency = cappedDay;
                //最后一天时长
                double lastTime = calDiff - cappedDay * 24;
                if (lastTime >= cappedTime){
                    //若最后一天时长仍达到封顶时长
                    cappedFrequency++;
                    fee = cappedFrequency * cappedPrice;
                    map.put("fee",String.valueOf(fee));
                    return map;
                }
                fee = cappedFrequency * cappedPrice + lastTime * unitPrice;
                map.put("fee",String.valueOf(fee));
                return map;
            }
        }else {
            //不封顶的情况下
            fee = calDiff * unitPrice;
            map.put("fee",String.valueOf(fee));
            return map;
        }

    }

    /**
     * 按 "yyyy-MM-dd HH:mm:ss" 格式返回当前时间
     * @author 文
     * @return
     */
    private String now() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(new Date());
    }
}
